﻿using FileToVideo.AddFunc;
using FileToVideo.Config;
using FileToVideo.Enums;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FileToVideo.Helpers
{
    /// <summary>
    /// 默认纯色帧数据工具
    /// </summary>
    public class DefaultColorFrameUtils : IDisposable
    {
        /// <summary>
        /// 版本控制
        /// <br />
        /// 当前数据工具版本,用于数据兼容性判断
        /// <br />
        /// 规则: 主版本.次版本.修订版本(如: 1.0.0)
        /// <br />
        /// 当主版本变化时,表示不兼容的重大变化
        /// </summary>
        [System.ComponentModel.Description("版本号")]
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] // 防止在智能感知中显示此属性
        public static string Version { get; } = Setting.Version;

        /// <summary>
        /// 编码方式
        /// </summary>
        public EncryptMode encryptMode = EncryptMode.AES;

        /// <summary>
        /// 纯色帧检测器
        /// </summary>
        public PureColorFrameDetector pureColorFrameDetector;

        /// <summary>
        /// 起始帧颜色列表
        /// <br />
        /// 默认视频中出现此纯色序列后
        /// 的纯色帧为初始化数据
        /// <br />
        /// 红色->绿色->蓝色->黑色->白色
        /// </summary>
        private List<Color> startColors = new List<Color>()
        {
            Color.FromArgb(255, 0, 0),       // 红色
            Color.FromArgb(0, 255, 0),       // 绿色
            Color.FromArgb(0, 0, 255),       // 蓝色
            Color.FromArgb(0, 0, 0),         // 黑色
            Color.FromArgb(255, 255, 255)    // 白色
        };

        /// <summary>
        /// 起始帧颜色列表
        /// <br />
        /// 给外部访问用(只读)
        /// </summary>
        public List<Color> StartColors
        {
            get
            {
                return startColors.DeepCopy();
            }
        }

        /// <summary>
        /// 帧重复数量
        /// </summary>
        public int frameRepetition = Setting.frameRepetition;

        /// <summary>
        /// 状态机阶段索引
        /// </summary>
        public int stageIndex = 0;

        /// <summary>
        /// 错误计数
        /// </summary>
        public int errorCount = 0;

        /// <summary>
        /// 最大错误计数
        /// </summary>
        public int maxErrorCount = 5;

        /// <summary>
        /// 默认Base64密钥
        /// </summary>
        private readonly string base64Key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        /// <summary>
        /// 默认Base64密钥颜色对照字典
        /// </summary>
        private readonly Dictionary<char, Color> base64KeyDict = new Dictionary<char, Color>();

        /// <summary>
        /// 颜色生成器
        /// </summary>
        private ColorGenerator colorGenerator;

        /// <summary>
        /// 构造默认纯色帧数据工具
        /// </summary>
        /// <param name="encryptMode">编码方式</param>
        /// <param name="videoPath">视频文件地址</param>
        /// <param name="startColors">开始颜色列表</param>
        /// <param name="frameRepetition">帧重复数量</param>
        public DefaultColorFrameUtils(
            EncryptMode encryptMode,
            string videoPath,
            List<Color> startColors = null,
            int frameRepetition = Setting.frameRepetition,
            bool isRead = true
        )
        {
            this.encryptMode = encryptMode;
            this.pureColorFrameDetector = new PureColorFrameDetector(videoPath, isRead);
            this.startColors = startColors ?? this.startColors;
            this.frameRepetition = frameRepetition;

            // 初始化Base64密钥颜色对照字典
            InitializeBase64KeyDict();
        }

        /// <summary>
        /// 构造默认纯色帧数据工具
        /// </summary>
        /// <param name="encryptMode"></param>
        /// <param name="videoPath"></param>
        /// <param name="isRead"></param>
        public DefaultColorFrameUtils(
            EncryptMode encryptMode,
            string videoPath,
            bool isRead = true
        ) : this(encryptMode, videoPath, null, Setting.frameRepetition, isRead)
        {

        }

        /// <summary>
        /// 初始化Base64密钥颜色对照字典
        /// </summary>
        private void InitializeBase64KeyDict()
        {
            this.colorGenerator = new ColorGenerator(base64Key.Length);
            var colors = colorGenerator.GeneratedColors;

            for (int i = 0; i < base64Key.Length; i++)
            {
                base64KeyDict[base64Key[i]] = colors[i];
            }
        }

        /// <summary>
        /// 读取初始化数据
        /// <br />
        /// 改写成会调用 Loading 的版本
        /// </summary>
        /// <returns></returns>
        public async Task<string> ReadStartData()
        {
            try
            {
                Item.logger.Log("开始检测起始颜色序列...");

                // 1. 首先检测起始颜色序列
                int sequenceStartIndex = await this.pureColorFrameDetector.DetectColorSequenceFromIndex(
                    startColors,
                    startIndex: 0,
                    minSequenceLength: Setting.minSequenceLength,  // 允许最少10帧
                    maxSequenceLength: Setting.maxSequenceLength, // 最大为帧重复数量
                    colorTolerance: Setting.colorTolerance   // 颜色容差
                );

                if (sequenceStartIndex == -1)
                {
                    throw new Exception("未找到起始颜色序列");
                }

                Item.logger.Log($"找到起始颜色序列，起始帧索引: {sequenceStartIndex}");

                // 2. 计算数据开始位置（起始序列结束后的位置）
                int dataStartIndex = sequenceStartIndex + (startColors.Count * frameRepetition);
                Item.logger.Log($"数据开始位置: {dataStartIndex}");

                // 3. 从数据开始位置读取Base64编码的数据
                string result = await ReadBase64Data(dataStartIndex);
                Item.logger.Log($"读取到数据: {result}");

                return result;
            }
            catch (Exception ex)
            {
                throw new Exception($"读取起始数据失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 从指定位置开始读取Base64编码的数据
        /// </summary>
        private async Task<string> ReadBase64Data(
            int startIndex
        )
        {
            var detector = this.pureColorFrameDetector;
            StringBuilder resultBuilder = new StringBuilder();
            Color lastColor = Color.Empty;
            int sameColorCount = 0;

            // 设置起始帧
            detector.ResetIndex(startIndex);

            // 启动 Loading 界面
            using (Loading loading = new Loading(detector.TotalFrames, "开始读取首帧数据..."))
            {
                loading.Show();
                loading.Update(startIndex);

                return await Task.Run(() =>
                {
                    for (int frameIndex = startIndex; frameIndex < detector.TotalFrames; frameIndex++)
                    {
                        // 获取下一帧纯色帧
                        //var (currentFrameIndex, currentColor) = detector.GetNextPureColorFrameIndexAndColor();
                        var (currentFrameIndex, currentColor) = detector.GetNextPureColorFrameIndexAndColorNoCache();

                        if (currentFrameIndex == -1)
                        {
                            Item.logger.Log("未找到更多纯色帧，数据读取结束");
                            break;
                        }
                        else
                        {
                            loading.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                loading.Update(currentFrameIndex, "开始读取首帧数据" + ".".Repeat(frameIndex % 4));
                            }), System.Windows.Threading.DispatcherPriority.Background);
                        }

                        // 跳过当前帧索引到下一帧
                        frameIndex = currentFrameIndex;

                        // 查找最接近的Base64字符
                        char? currentChar = FindClosestBase64Char(currentColor);

                        if (currentChar.HasValue)
                        {
                            // 处理重复帧：如果颜色相同，计数增加
                            if (pureColorFrameDetector.IsColorMatch(currentColor, lastColor, Setting.colorTolerance))
                            {
                                sameColorCount++;
                            }
                            else
                            {
                                sameColorCount = 1;
                                lastColor = currentColor;
                            }

                            // 只有当相同颜色帧数达到frameRepetition时（或容忍一定误差），才添加字符
                            if (sameColorCount >= frameRepetition * 0.8) // 允许80%的误差
                            {
                                resultBuilder.Append(currentChar.Value);
                                // Item.logger.Log($"帧 {currentFrameIndex}: 颜色 {currentColor} -> 字符 '{currentChar.Value}', 重复计数: {sameColorCount}");

                                // 重置计数（因为我们已经处理了这一组重复帧）
                                sameColorCount = 0;

                                //// GC回收
                                //GC.Collect();
                            }
                        }
                        else
                        {
                            Item.logger.Log($"帧 {currentFrameIndex}: 颜色 {currentColor} 无法匹配到Base64字符");
                            errorCount++;

                            if (errorCount >= maxErrorCount)
                            {
                                Item.logger.Log("错误计数超过限制，停止读取");
                                break;
                            }
                        }

                        // 跳过已经检查的帧
                        frameIndex = currentFrameIndex;
                    }

                    return resultBuilder.ToString();
                });
            }
        }

        /// <summary>
        /// 计算颜色距离（使用欧几里得距离）
        /// </summary>
        public double CalculateColorDistance(Color color1, Color color2)
        {
            double rDiff = color1.R - color2.R;
            double gDiff = color1.G - color2.G;
            double bDiff = color1.B - color2.B;

            return Math.Sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff);
        }

        /// <summary>
        /// 查找最接近的Base64字符
        /// </summary>
        private char? FindClosestBase64Char(Color targetColor)
        {
            double minDistance = double.MaxValue;
            char? closestChar = null;

            foreach (var pair in base64KeyDict)
            {
                double distance = CalculateColorDistance(targetColor, pair.Value);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    closestChar = pair.Key;
                }
            }

            // 如果距离太大，认为不匹配
            if (minDistance > Setting.colorTolerance) // 可调整的阈值
            {
                return null;
            }

            return closestChar;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            pureColorFrameDetector?.Dispose();
        }
    }
}
